
; flat assembler source

include 'macro/if.inc'

macro _callarg proc,[arg]
{
	reverse pushd	arg
	common	call	proc
}

macro _fastcall proc,c,d,[arg]
{
	reverse pushd	arg
	common
	if ~ c eq ecx
		mov	ecx, c
	end if
	if ~ d eq edx
		mov	edx, d
	end if
	call	proc
}

NULL	equ 0

; ExceptionFlags:
;   EH_NONCONTINUABLE = 1
;   EH_UNWINDING      = 2
;   EH_EXIT_UNWIND    = 4

format ELF

public luacon_process_pcall as '.luacon_process_pcall'
public luacon_swap64 as '.luacon_swap64'
public _draw_blockic as '.sdl_translate_draw_blockic.asm'

extrn '_abort'				as abort
extrn '_FreeLibrary@4'			as FreeLibrary
extrn '_GetProcAddress@8'		as GetProcAddress
extrn '_LoadLibraryA@4' 		as LoadLibrary
extrn '_lua_pcall'			as lua_pcall
extrn '.luacon_pcall_multret.0' 	as lua_pcall_multret
extrn '.luacon_pcall_resetstkoflw'	as luacon_pcall_resetstkoflw
extrn '_RtlUnwind@16'			as RtlUnwind

section '.text' executable align 16

luacon_process_pcall:
	pusha
	push	eax
	push	.excpt
	push	dword [fs:0]
	mov	[fs:0], esp
	call	lua_pcall_multret	; eax = lua_State (L)
	mov	esp, [fs:0]
  .epilog:
	mov	[esp+40], eax
	pop	dword [fs:0]
	add	esp, 8
	popa
	ret
	align	16
  .excpt:
	push	esi ebx
	mov	ebx, [esp+4*3]
	mov	esi, [esp+4*4]
	test	byte [ebx+4], 6 ; EH_UNWINDING | EH_EXIT_UNWIND
	jz	.excpt1
	xor	eax, eax
	inc	eax
	pop	ebx esi
	ret
  .excpt1:
	push	esi
	push	dword [ebx]
	_callarg RtlUnwind, esi, .excpt_target_ip, ebx, 0
  .excpt_target_ip:
	pop	ecx esp
	.if	ecx = 0xC00000FD
		call	luacon_pcall_resetstkoflw
		test	eax, eax
		jz	.abort
	.endif
	or	eax, -1
	jmp	.epilog
	align	16
  .abort:
	call	abort
	int3
	align	16

luacon_swap64:
	push	ebp edi esi ebx
	mov	ebp, eax
	mov	esi, edx
	mov	edi, ecx
	mov	eax, [ebp]
	mov	edx, [ebp+4]
	mov	ebx, [esi]
	mov	ecx, [esi+4]
  .1:
	lock	cmpxchg8b [ebp]
	jnz	.1
	mov	[edi], eax
	mov	[edi+4], edx
	pop	ebx esi edi ebp
	ret
	align	16

_draw_blockic:
	; expected: CHRW = 8 and CHRH = 16
	; no callee saved registers
	rept	8 n:0 {
		mov	esi, ecx
		test	eax, 0x80 shr n
		cmovz	esi, edx
		movd	xmm#n, esi
		pshufd	xmm#n, xmm#n, 0
	}
	lea	esi, [ebx*3]
	rept	4 a:0 {
		irp	b, 0,ebx,ebx*2,esi \{
			rept	2 c:a*2 \\{
				movups	[edi+b+(c and 1)*16], xmm\\#c
			\\}
		\}
		if a < 3
			lea	edi, [edi+ebx*4]
		end if
	}
	ret
	align	16

; section '.data' writeable align 16

; section '.rdata' align 16